package com.core.Window.Main;

import com.Gameplay.Combat.CombatManagement.CombatManagement;
import com.Gameplay.character.Role.impl.roleJJH;
import com.Gameplay.character.Role.impl.roleKK;
import com.Gameplay.character.Role.parentRole;
import com.Input.InputManager;


import com.NetWork.Netty.Client;
import com.NetWork.Netty.Server;
import com.NetWork.PlayerStatus.UpdateSystem;
import com.Rendering.Renderer;

import com.Stage.GameStageManagement;
import com.Utils.Timer;
import com.Rendering.StageScene.GameScene;
import com.Utils.Clock;
import javafx.animation.AnimationTimer;
import javafx.application.Application;

import javafx.scene.image.Image;

import javafx.scene.input.KeyCode;
import javafx.stage.Stage;


import java.util.ArrayList;
import java.util.Objects;


public class Game extends Application {
    public static int ClientID = 1;
    private Image image;
    private static Stage stage;
    private final int width = 1440;
    private final int height = 900;
    private static GameStageManagement gameStageManagement;
    ;
    private static final Game GameInstance = new Game();
    //初始化所有场景
    private GameStageManagement gameStageManagementInstance;

    private Renderer renderer;
    private Timer timer = new Timer(20);
    //注册键盘监听 简易版
    private InputManager inputManager;

    //测试用例
    private parentRole p1;
    private parentRole p2;
    //网络测试
    private UpdateSystem updateSystem;
    private static boolean isJoin = false;

    //初始化时钟类
    private static Clock clock;
    //资源初始化

    @Override
    public void init() {
        clock = new Clock();
        gameStageManagement = new GameStageManagement();


        String iconPath = "/Icon.png";
        image = new Image(Objects.requireNonNull(
                Game.class.getResourceAsStream(iconPath),
                "Resource not found: " + iconPath
        ));

        renderer = new Renderer(gameStageManagement.getMapByName("Training").getGameScene());
        inputManager = new InputManager();

        p1 = new roleKK(1, 1, "KK");
        p2 = new roleJJH(2, 2, "JJH");
        p2.GamesetCurrentX((double) width + (double) width / 4);
        updateSystem = new UpdateSystem(p1, p2);
    }

    //主线程
    @Override
    public void start(Stage primaryStage) {
        stage = primaryStage;
        // 设置标题和图标
        stage.setTitle("StickManDuel");
        primaryStage.getIcons().add(image);
        //设置舞台高宽
        stage.setWidth(width);
        stage.setHeight(height);
        //设置加载初始场景
        renderer.GuiMainMenuRender();
        //注册键盘监听
        inputManager.setScene(gameStageManagement.getMapStages());

        new Thread(() -> inputManager.run()).start();

        new AnimationTimer() {
            @Override
            public void handle(long l) {
                if (!Client.isConnected) {
                    return;
                }
                RunGameLoop();
            }
        }.start();
        primaryStage.show();
    }

    @Override
    public void stop() {
        //关闭服务端
        Server.stopServer();
        //关闭客户端
        Client.stopClient();
        System.exit(0);
    }

    //游戏更新部分
    private void RunGameLoop() {
        timer.updateTimer();
        for (int j = 0; j < timer.elapsedTicks; j++) {
            netWorkUpdate();
            RunTick();
            netWorkMessageSend(p1, p2);
        }
        updateRender(timer.renderPartialTicks);

    }

    private void RunTick() {
        if (!isJoin) {
            return;
        }
        clock.updateTime();
        ArrayList<KeyCode> keyCodes = new ArrayList<>();
        KeyCode keyCode;
        while ((keyCode = inputManager.getReleased().poll()) != null) {
            keyCodes.add(keyCode);
        }
        if (ClientID == 1) {
            p1.Moving(p2);
            p1.Attacking(keyCodes, p2);
            p1.boundaryDetection(p2);
        } else {
            p2.Moving(p1);
            p2.Attacking(keyCodes, p1);
            p2.boundaryDetection(p1);
        }
    }

    private void netWorkUpdate() {
        if (!Client.p1States.isEmpty() && !Client.p2States.isEmpty()) {
            //clock setting
            if (!isJoin && Client.isConnected) {
                isJoin = true;
                clock.setGameStartTime();
            }
            updateSystem.update(Client.p1States.poll(), Client.p2States.poll());
        }
        Client.p1States.clear();
        Client.p2States.clear();
    }

    private void netWorkMessageSend(parentRole p1, parentRole p2) {
        if (!Client.isConnected) {
            return;
        }
        if (ClientID == 1) {
            Client.sedMessage(p1);
        } else if (ClientID == 2) {
            Client.sedMessage(p2);
        }
    }

    private void updateRender(float partialTicks) {
        //Render为渲染 draw 为绘制 故所有UI相关的为draw()方法
        renderer.updateCamara(p1, p2, partialTicks);
        renderer.draw(p1, p2);
        renderer.updateEntityRender(p1, p2, partialTicks);
    }


    public static Stage getStage() {
        return stage;
    }

    public static Game getInstance() {
        return GameInstance;
    }

    public static long getSystemTime() {
        return System.nanoTime() / 1000000L;
    }


    public int getHeight() {
        return height;
    }

    public int getWidth() {
        return width;
    }

    public void setGameScene() {
        stage.setScene(gameStageManagement.getMapByName("Training").getGameScene().getScene());
    }

    public Clock getClock() {
        return clock;
    }
}